package com.tmzn.jwt;

import cn.hutool.core.util.StrUtil;
import com.tmzn.domain.ImsMcMembers;
import com.tmzn.jwt.bean.IJwtAble;
import com.tmzn.jwt.bean.MyIJwtAble;
import com.tmzn.service.UserService;
import com.tmzn.util.SpringUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.kafka.common.config.ConfigException;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 我有故事，你有酒么？
 * JKhaled created by yunqisong@foxmail.com 2017/7/22
 * FOR : Jwt操作工具类
 */
public class JwtKit {

    public static String header = "Authorization";  // 默认请求头标识符
    public static String tokenPrefix = "Bearer ";    // 默认token前缀
    public static String secret = "default";         // 默认私钥
//    public static Long expiration = 604800L;          // 默认失效时间(秒)
    public static UserService userService = null;//  需要注入的服务参数
    
    public static Long expiration = 60 * 60L;
    
    public static int expirationTime = 60 * 60;
    public static JwtStore jwtStore = new JwtStore();

    private static final String CLAIM_KEY_USERNAME = "sub";
    private static final String CLAIM_KEY_CREATED = "created";

    static {    // token的反序列化
//        readFile();
    }

    public JwtKit(){
        JwtKit.userService = SpringUtils.getBean(UserService.class);
    }


    /**
     * 获取当前的登录用户
     * @return
     */
    public static MyIJwtAble getLoginUser(){
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        String authorization = request.getHeader("Authorization");
        return getUser(authorization);
    }
    /**
     * 重构缓存
     */
    public static void storeReset() {
//        jwtStore = Kv.create();
    }

    /**
     * 通过 用户名密码 获取 token 如果为null，那么用户非法
     *
     * @return
     */
    public static String getToken(ImsMcMembers userObj) {
        String mobile = userObj.getMobile();
        MyIJwtAble user = new MyIJwtAble();
        user.setId(userObj.getUid());
        user.setTel(mobile);
        // 构建服务器端储存对象
        String token = generateToken(mobile);
        jwtStore.set(token, user);// 在服务器端储存jwtBean
        jwtStore.expire(token, expirationTime);
        // 用userName创建token
        return tokenPrefix + token;
    }
    

    public static void logout(String token){
    	 String authToken = token.substring(JwtKit.tokenPrefix.length());
    	jwtStore.del(authToken);
    }
    
    public static MyIJwtAble getUser(String authHeader){
    	  if (StrUtil.isBlank(authHeader) || authHeader.length() < JwtKit.tokenPrefix.length()) {
              return null;
          }
	     String authToken = authHeader.substring(JwtKit.tokenPrefix.length());
	     MyIJwtAble me = null;
    	 String jwtUser = JwtKit.getJwtUser(authToken);                      // 从token中解析出jwtAble
         if (jwtUser != null){
             Date created = JwtKit.getCreatedDateFormToken(authToken);
             me = (MyIJwtAble) JwtKit.getJwtBean(authToken,created);
             if(me == null){
            	 return null;
             }
             Long ttl = jwtStore.ttl(authToken);
             SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
             String format = sdf.format(System.currentTimeMillis()+ttl*1000);
             me.set("expiredDate", format);
             me.set("token", authHeader);
         }
         return me;
    }
    /**
     * 通过 旧的token来交换新的token
     *
     * @param token
     * @return
     */
    public static String refreshToken(String token) {
        if (userService == null) {
            throw new ConfigException("userService", "空/null");
        }
        if (token == null || token.length() < tokenPrefix.length()) {
            throw new ConfigException("token", "被解析");
        }
        String trueToken = token.substring(tokenPrefix.length(), token.length());
        if (isTokenExpired(trueToken)) { // 如果已经过期
            // 解析出用户名
            String userName = getJwtUser(trueToken);
            IJwtAble jwtBean = (IJwtAble) jwtStore.get(userName);
            if(jwtBean == null) {
                return token;
            }
            return generateToken(userName); // 在此匹配生成token
        }else{
        	
        }
        return token;
    }

    /**
     * 从用户Token中获取用户名信息
     *
     * @param authToken
     * @return
     */
    public static String getJwtUser(String authToken) {
        String jwtUser = null;
        try {
            final Claims claims = getClaimsFromToken(authToken);
            jwtUser = claims != null ? claims.getSubject() : null;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return jwtUser;
        }
    }

    /**
     * 获取 getJwtBean 对象
     *
     * @param jwtUser
     * @return
     */
    public static MyIJwtAble getJwtBean(String jwtUser, Date created) {
        MyIJwtAble jwtBean = null;
        try {
            jwtBean = (MyIJwtAble) jwtStore.get(jwtUser);
          
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jwtBean;
    }

    /**
     * 获取Token的过期日期
     *
     * @param token
     * @return
     */
    public static Date getExpirationDateFromToken(String token) {
        Date expiration;
        try {
            final Claims claims = getClaimsFromToken(token);
            expiration = claims.getExpiration();
        } catch (Exception e) {
            expiration = null;
        }
        return expiration;
    }

    /**
     * 获取用户Token的创建日期
     *
     * @param authToken
     * @return
     */
    public static Date getCreatedDateFormToken(String authToken) {
        Date creatd;
        try {
            final Claims claims = getClaimsFromToken(authToken);
            creatd = new Date((Long) claims.get(CLAIM_KEY_CREATED)); // 把时间戳转化为日期类型
        } catch (Exception e) {
            creatd = null;
        }

        return creatd;
    }

    /**
     * 判断Token是否已经过期
     *
     * @param token
     * @return
     */
    public static Boolean isTokenExpired(String token) {
//        final Date expiration = getExpirationDateFromToken(token);
//        return expiration.before(new Date());
    	return false;
    }

    /**
     * 将Token信息解析成Claims
     *
     * @param token
     * @return
     */
    private static Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            claims = null;
        }
        return claims;
    }

    /**
     * 根据用户信息生成Token
     *
     * @param userName
     * @return
     */
    private static String generateToken(String userName) {
        Map<String, Object> claims = new HashMap<String, Object>();
        claims.put(CLAIM_KEY_USERNAME, userName);
        claims.put(CLAIM_KEY_CREATED, new Date());
        return generateToken(claims);
    }

    /**
     * 根据Claims信息来创建Token
     *
     * @param claims
     * @returns
     */
    private static String generateToken(Map<String, Object> claims) {
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(generateExpirationDate())
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }

    /**
     * 生成令牌的过期日期
     *
     * @return
     */
    private static Date generateExpirationDate() {
        return new Date(System.currentTimeMillis() + expiration * 1000);
    }


}
